#include "st-private.h"
#include "st-settings.h"
#include <gtk/gtk.h>
+#include <math.h>
#include <string.h>
#include <glib.h>
guint width;
guint height;
- guint scale;
+ guint paint_scale;
+ gfloat resource_scale;
GSList *actors;
GtkIconInfo *icon_info;
impl_load_pixbuf_file (GFile *file,
int available_width,
int available_height,
- int scale,
+ int paint_scale,
+ float resource_scale,
GError **error)
{
GdkPixbuf *pixbuf = NULL;
if (g_file_load_contents (file, NULL, &contents, &size, NULL, error))
{
+ int scale = ceilf (paint_scale * resource_scale);
pixbuf = impl_load_pixbuf_data ((const guchar *) contents, size,
available_width, available_height,
scale,
g_assert (data != NULL);
g_assert (data->file != NULL);
- pixbuf = impl_load_pixbuf_file (data->file, data->width, data->height, data->scale, &error);
+ pixbuf = impl_load_pixbuf_file (data->file, data->width, data->height,
+ data->paint_scale, data->resource_scale,
+ &error);
if (error != NULL)
g_task_return_error (result, error);
* if the icon must not be recolored
* @icon: the #GIcon to load
* @size: Size of themed
- * @scale: Scale factor of display
+ * @paint_scale: Scale factor of display
+ * @resource_scale: Resource scale factor
*
* This method returns a new #ClutterActor for a given #GIcon. If the
* icon isn't loaded already, the texture will be filled
StThemeNode *theme_node,
GIcon *icon,
gint size,
- gint scale)
+ gint paint_scale,
+ gfloat resource_scale)
{
AsyncTextureLoadData *request;
ClutterActor *actor;
+ gint scale;
char *gicon_string;
char *key;
+ float actor_size;
GtkIconTheme *theme;
GtkIconInfo *info;
StTextureCachePolicy policy;
else
lookup_flags |= GTK_ICON_LOOKUP_DIR_LTR;
- info = gtk_icon_theme_lookup_by_gicon_for_scale (theme, icon, size, scale, lookup_flags);
+ scale = ceilf (paint_scale * resource_scale);
+ info = gtk_icon_theme_lookup_by_gicon_for_scale (theme, icon,
+ size, scale,
+ lookup_flags);
if (info == NULL)
return NULL;
g_free (gicon_string);
actor = create_invisible_actor ();
- clutter_actor_set_size (actor, size * scale, size * scale);
-
+ actor_size = size * paint_scale;
+ clutter_actor_set_size (actor, actor_size, actor_size);
if (ensure_request (cache, key, policy, &request, actor))
{
/* If there's an outstanding request, we've just added ourselves to it */
request->colors = colors ? st_icon_colors_ref (colors) : NULL;
request->icon_info = info;
request->width = request->height = size;
- request->scale = scale;
+ request->paint_scale = paint_scale;
+ request->resource_scale = resource_scale;
load_texture_async (cache, request);
}
typedef struct {
GFile *gfile;
gint grid_width, grid_height;
- gint scale_factor;
+ gint paint_scale;
+ gfloat resource_scale;
ClutterActor *actor;
GFunc load_callback;
gpointer load_callback_data;
gpointer user_data)
{
AsyncImageData *data = user_data;
- gdk_pixbuf_loader_set_size (loader,
- width * data->scale_factor,
- height * data->scale_factor);
+ int scale = ceilf (data->paint_scale * data->resource_scale);
+
+ gdk_pixbuf_loader_set_size (loader, width * scale, height * scale);
}
static void
GList *res = NULL;
GdkPixbuf *pix;
gint width, height, y, x;
+ gint scale_factor;
GdkPixbufLoader *loader;
GError *error = NULL;
gchar *buffer = NULL;
pix = gdk_pixbuf_loader_get_pixbuf (loader);
width = gdk_pixbuf_get_width (pix);
height = gdk_pixbuf_get_height (pix);
- for (y = 0; y < height; y += data->grid_height * data->scale_factor)
+ scale_factor = ceilf (data->paint_scale * data->resource_scale);
+ for (y = 0; y < height; y += data->grid_height * scale_factor)
{
- for (x = 0; x < width; x += data->grid_width * data->scale_factor)
+ for (x = 0; x < width; x += data->grid_width * scale_factor)
{
GdkPixbuf *pixbuf = gdk_pixbuf_new_subpixbuf (pix, x, y,
- data->grid_width * data->scale_factor,
- data->grid_height * data->scale_factor);
+ data->grid_width * scale_factor,
+ data->grid_height * scale_factor);
g_assert (pixbuf != NULL);
res = g_list_append (res, pixbuf);
}
* @file: A #GFile
* @grid_width: Width in pixels
* @grid_height: Height in pixels
- * @scale: Scale factor of the display
+ * @paint_scale: Scale factor of the display
* @load_callback: (scope async) (nullable): Function called when the image is loaded, or %NULL
* @user_data: Data to pass to the load callback
*
* This function reads a single image file which contains multiple images internally.
* The image file will be divided using @grid_width and @grid_height;
- * note that the dimensions of the image loaded from @path
+ * note that the dimensions of the image loaded from @path
* should be a multiple of the specified grid dimensions.
*
* Returns: (transfer none): A new #ClutterActor
GFile *file,
gint grid_width,
gint grid_height,
- gint scale,
+ gint paint_scale,
+ gfloat resource_scale,
GFunc load_callback,
gpointer user_data)
{
GTask *result;
ClutterActor *actor = clutter_actor_new ();
+ g_return_val_if_fail (G_IS_FILE (file), NULL);
+ g_assert (paint_scale > 0);
+ g_assert (resource_scale > 0);
+
data = g_new0 (AsyncImageData, 1);
data->grid_width = grid_width;
data->grid_height = grid_height;
- data->scale_factor = scale;
+ data->paint_scale = paint_scale;
+ data->resource_scale = resource_scale;
data->gfile = g_object_ref (file);
data->actor = actor;
data->load_callback = load_callback;
* @file: a #GFile of the image file from which to create a pixbuf
* @available_width: available width for the image, can be -1 if not limited
* @available_height: available height for the image, can be -1 if not limited
- * @scale: scale factor of the display
+ * @paint_scale: scale factor of the display
+ * @resource_scale: Resource scale factor
*
* Asynchronously load an image. Initially, the returned texture will have a natural
* size of zero. At some later point, either the image will be loaded successfully
GFile *file,
int available_width,
int available_height,
- int scale)
+ int paint_scale,
+ gfloat resource_scale)
{
ClutterActor *actor;
AsyncTextureLoadData *request;
StTextureCachePolicy policy;
gchar *key;
+ int scale;
- key = g_strdup_printf (CACHE_PREFIX_FILE "%u", g_file_hash (file));
+ scale = ceilf (paint_scale * resource_scale);
+ key = g_strdup_printf (CACHE_PREFIX_FILE "%u%d", g_file_hash (file), scale);
policy = ST_TEXTURE_CACHE_POLICY_NONE; /* XXX */
request->policy = policy;
request->width = available_width;
request->height = available_height;
- request->scale = scale;
+ request->paint_scale = paint_scale;
+ request->resource_scale = resource_scale;
load_texture_async (cache, request);
}
GFile *file,
int available_width,
int available_height,
- int scale,
+ int paint_scale,
+ gfloat resource_scale,
GError **error)
{
ClutterContent *image;
GdkPixbuf *pixbuf;
char *key;
- key = g_strdup_printf (CACHE_PREFIX_FILE "%u", g_file_hash (file));
+ key = g_strdup_printf (CACHE_PREFIX_FILE "%u%f", g_file_hash (file), resource_scale);
texdata = NULL;
image = g_hash_table_lookup (cache->priv->keyed_cache, key);
if (image == NULL)
{
- pixbuf = impl_load_pixbuf_file (file, available_width, available_height, scale, error);
+ pixbuf = impl_load_pixbuf_file (file, available_width, available_height,
+ paint_scale, resource_scale, error);
if (!pixbuf)
goto out;
GFile *file,
int available_width,
int available_height,
- int scale,
+ int paint_scale,
+ gfloat resource_scale,
GError **error)
{
cairo_surface_t *surface;
GdkPixbuf *pixbuf;
char *key;
- key = g_strdup_printf (CACHE_PREFIX_FILE_FOR_CAIRO "%u", g_file_hash (file));
+ key = g_strdup_printf (CACHE_PREFIX_FILE_FOR_CAIRO "%u%f", g_file_hash (file), resource_scale);
surface = g_hash_table_lookup (cache->priv->keyed_surface_cache, key);
if (surface == NULL)
{
- pixbuf = impl_load_pixbuf_file (file, available_width, available_height, scale, error);
+ pixbuf = impl_load_pixbuf_file (file, available_width, available_height,
+ paint_scale, resource_scale, error);
if (!pixbuf)
goto out;
* st_texture_cache_load_file_to_cogl_texture: (skip)
* @cache: A #StTextureCache
* @file: A #GFile in supported image format
- * @scale: Scale factor of the display
+ * @paint_scale: Scale factor of the display
+ * @resource_scale: Resource scale factor
*
* This function synchronously loads the given file path
* into a COGL texture. On error, a warning is emitted
CoglTexture *
st_texture_cache_load_file_to_cogl_texture (StTextureCache *cache,
GFile *file,
- gint scale)
+ gint paint_scale,
+ gfloat resource_scale)
{
CoglTexture *texture;
GError *error = NULL;
texture = st_texture_cache_load_file_sync_to_cogl_texture (cache, ST_TEXTURE_CACHE_POLICY_FOREVER,
- file, -1, -1, scale, &error);
+ file, -1, -1, paint_scale, resource_scale,
+ &error);
if (texture == NULL)
{
* st_texture_cache_load_file_to_cairo_surface:
* @cache: A #StTextureCache
* @file: A #GFile in supported image format
- * @scale: Scale factor of the display
+ * @paint_scale: Scale factor of the display
+ * @resource_scale: Resource scale factor
*
* This function synchronously loads the given file path
* into a cairo surface. On error, a warning is emitted
cairo_surface_t *
st_texture_cache_load_file_to_cairo_surface (StTextureCache *cache,
GFile *file,
- gint scale)
+ gint paint_scale,
+ gfloat resource_scale)
{
cairo_surface_t *surface;
GError *error = NULL;
surface = st_texture_cache_load_file_sync_to_cairo_surface (cache, ST_TEXTURE_CACHE_POLICY_FOREVER,
- file, -1, -1, scale, &error);
+ file, -1, -1, paint_scale, resource_scale,
+ &error);
if (surface == NULL)
{
texture_cache = st_texture_cache_get_default ();
g_object_get (node->context, "scale-factor", &scale_factor, NULL);
- surface = st_texture_cache_load_file_to_cairo_surface (texture_cache, file, scale_factor);
+ surface = st_texture_cache_load_file_to_cairo_surface (texture_cache, file,
+ scale_factor,
+ resource_scale);
if (surface == NULL)
return NULL;
cairo_matrix_init_identity (&matrix);
+ if (resource_scale != 1.0)
+ {
+ background_image_width /= resource_scale;
+ background_image_height /= resource_scale;
+
+ cairo_matrix_scale (&matrix, resource_scale, resource_scale);
+ }
+
get_background_scale (node,
width, height,
background_image_width, background_image_height,
- resource_scale, &scale_w, &scale_h);
+ &scale_w, &scale_h);
if ((scale_w != 1) || (scale_h != 1))
cairo_matrix_scale (&matrix, 1.0/scale_w, 1.0/scale_h);
if (interior_path != NULL)
cairo_path_destroy (interior_path);
- texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx, texture_width,
+ texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx,
+ texture_width,
texture_height,
CLUTTER_CAIRO_FORMAT_ARGB32,
rowstride,
}
static gboolean
-st_theme_node_load_border_image (StThemeNode *node)
+st_theme_node_load_border_image (StThemeNode *node,
+ gfloat resource_scale)
{
if (node->border_slices_texture == NULL)
{
g_object_get (node->context, "scale-factor", &scale_factor, NULL);
node->border_slices_texture = st_texture_cache_load_file_to_cogl_texture (st_texture_cache_get_default (),
- file, scale_factor);
+ file, scale_factor,
+ resource_scale);
if (node->border_slices_texture == NULL)
goto out;
}
static gboolean
-st_theme_node_load_background_image (StThemeNode *node)
+st_theme_node_load_background_image (StThemeNode *node,
+ gfloat resource_scale)
{
if (node->background_texture == NULL)
{
background_image_shadow_spec = st_theme_node_get_background_image_shadow (node);
node->background_texture = st_texture_cache_load_file_to_cogl_texture (st_texture_cache_get_default (),
- background_image, scale_factor);
+ background_image, scale_factor,
+ resource_scale);
if (node->background_texture == NULL)
goto out;
if (box_shadow_spec && !has_inset_box_shadow)
{
- if (st_theme_node_load_border_image (node))
+ if (st_theme_node_load_border_image (node, resource_scale))
state->box_shadow_pipeline = _st_create_shadow_pipeline (box_shadow_spec,
node->border_slices_texture,
state->resource_scale);
for (corner_id = 0; corner_id < 4; corner_id++)
if (state->corner_material[corner_id] == NULL)
state->corner_material[corner_id] =
- st_theme_node_lookup_corner (node, width, resource_scale, height, corner_id);
+ st_theme_node_lookup_corner (node, width, height, resource_scale, corner_id);
}
if (had_box_shadow)
}
if (state->prerendered_pipeline != NULL ||
- st_theme_node_load_border_image (node))
+ st_theme_node_load_border_image (node, resource_scale))
{
if (state->prerendered_pipeline != NULL)
{
st_theme_node_paint_outline (node, framebuffer, box, paint_opacity);
if (state->prerendered_pipeline == NULL &&
- st_theme_node_load_background_image (node))
+ st_theme_node_load_background_image (node, resource_scale))
{
ClutterActorBox background_box;
ClutterActorBox texture_coords;